
use actix_web::{ web, HttpResponse};
use dbaccess::course::{get_course_details_db, get_course_for_teacher_id, post_new_course_db};

use crate::dbaccess::course::{delete_course_db, update_course_details_db};
use crate::errors::MyError;
use crate::models::course::{CreateCourse, UpdateCourse};
use crate::state::AppState;
#[path = "../dbaccess/mod.rs"]
mod dbaccess;

#[path = "../models/mod.rs"]
pub mod models;
// pub async fn health_check_handler(app_state: web::Data<AppState>) -> HttpResponse {
//     println!("coming  in    health_check_handler");
//     let health_check_response = &app_state.health_check_response;
//     let mut visit_count = app_state.visit_count.lock().unwrap();
//     let response = format!("{} {} times   ", health_check_response, visit_count);
//     *visit_count += 1;
//     HttpResponse::Ok().json(&response)
// }

pub async fn new_course(new_course: web::Json<CreateCourse>,app_state: web::Data<AppState>) -> Result<HttpResponse,MyError> {
    post_new_course_db(&app_state.db,new_course.into()).await.
        map(|course| HttpResponse::Ok().json(course))
}


pub async fn get_course_for_teacher(params: web::Path<(usize,)>, app_state: web::Data<AppState>) -> Result<HttpResponse,MyError> {
    let teacher_id = i32::try_from(params.0).unwrap();
    get_course_for_teacher_id(&app_state.db, teacher_id)
        .await
        .map(|course| HttpResponse::Ok().json(course))
}

pub async fn get_course_detail(params: web::Path<(usize,usize)>, app_state: web::Data<AppState>) -> Result<HttpResponse,MyError> {
    let teacher_id = i32::try_from(params.0).unwrap();
    let course_id = i32::try_from(params.1).unwrap();
    get_course_details_db(&app_state.db, teacher_id,course_id)
        .await
        .map(|course| HttpResponse::Ok().json(course))

}

pub async fn delete_course(app_state: web::Data<AppState>,params: web::Path<(i32,i32)>)-> Result<HttpResponse,MyError> {
    let teacher_id = i32::try_from(params.0).unwrap();
    let course_id = i32::try_from(params.1).unwrap();
    delete_course_db(&app_state.db, teacher_id, course_id)
    .await
    .map(|course| HttpResponse::Ok().json(course))
}

pub async fn update_course_details(app_state: web::Data<AppState>,update_course: web::Json<UpdateCourse>,params: web::Path<(i32,i32)>) -> Result<HttpResponse,MyError> {
    let teacher_id = i32::try_from(params.0).unwrap();
    let course_id = i32::try_from(params.1).unwrap();
    update_course_details_db(&app_state.db,teacher_id,course_id,update_course.into())
        .await
        .map(|course| HttpResponse::Ok().json(course))
}

#[cfg(test)]
mod tests {
    use super::*;
    use actix_web::http::{ StatusCode};
    use std::sync::Mutex;
    use crate::state::AppState;
    use dotenv::dotenv;
    use sqlx::postgres::PgPoolOptions;
    use std::env;
    use serde::Serialize;
    use sqlx::encode::IsNull::No;

    // #[actix_rt::test]
    // #[ignore]
    // async fn post_course_test(){
    //     dotenv().ok();
    //     let db_url = env::var("DATABASE_URL").expect("DATABASE_URL is not set in .env");
    //     let db_pool = PgPoolOptions::new().connect(&db_url).await.unwrap();
    //     let app_state = web::Data::new(AppState {
    //         health_check_response: "".to_string(),
    //         visit_count: Mutex::new(0),
    //         db: db_pool,
    //     });
    //     let course = web::Json(Course {
    //         teacher_id: 1,
    //         name: "Test course".into(),
    //          time: None,
    //     });
    //     let resp = new_course(, app_state).await.unwrap();
    //     assert_eq!(resp.status(), StatusCode::OK);
    // }


    #[actix_rt::test]
    #[ignore]
    async fn get_all_courses_test(){
        dotenv().ok();
        let db_url = env::var("DATABASE_URL").expect("DATABASE_URL is not set in .env");
        let db_pool = PgPoolOptions::new().connect(&db_url).await.unwrap();
        let app_state = web::Data::new(AppState {
            health_check_response: "".to_string(),
            visit_count: Mutex::new(0),
            db: db_pool,
        });
        let teacher_id: web::Path<(usize,)> = web::Path::from((1,));
        let resp = get_course_for_teacher(teacher_id,app_state).await.unwrap();
        assert_eq!(resp.status(), StatusCode::OK);
    }
    #[actix_rt::test]
    #[ignore]
    async fn get_one_course_test(){
        dotenv().ok();
        let db_url = env::var("DATABASE_URL").expect("DATABASE_URL is not set in .env");
        let db_pool = PgPoolOptions::new().connect(&db_url).await.unwrap();
        let app_state = web::Data::new(AppState {
            health_check_response: "".to_string(),
            visit_count: Mutex::new(0),
            db: db_pool,
        });
        let params: web::Path<(usize,usize)> = web::Path::from((1,1));
        let resp = get_course_detail(params,app_state).await.unwrap();
        assert_eq!(resp.status(), StatusCode::OK);
    }
}
